<?php

namespace app\yy\services;

use app\yy\model\Website as WebModel;
use app\yy\model\Images as ImgModel;
use think\Db;
use think\Exception;

class Opencart extends BaseService
{

    public function yyToOpenCart($info, $dbstr, $category, $options, $products)
    {
        // 商品分类
        try {
            $category = $this->category($category, $dbstr);
        } catch (Exception $e) {
            WebModel::where('id', $info['id'])->update(['status' => 3, 'remark' => '商品分类迁移报错' . $e->getMessage(), 'end_time' => date('Y-m-d H:i:s')]);
            echo '商品分类迁移报错';
            die;
        }
        if (!$category) {
            WebModel::where('id', $info['id'])->update(['status' => 3, 'remark' => '商品分类迁移失败', 'end_time' => date('Y-m-d H:i:s')]);
            echo '商品分类迁移失败';
            die;
        }
        WebModel::where('id', $info['id'])->update(['remark' => '商品分类已迁移：' . date('Y-m-d H:i:s')]);

        // 选项
        try {
            [$db_option_name_list, $db_option_name_value] = $this->option($dbstr, $options);
        } catch (Exception $e) {
            WebModel::where('id', $info['id'])->update(['status' => 3, 'remark' => '商品选项迁移报错' . $e->getMessage(), 'end_time' => date('Y-m-d H:i:s')]);
            echo '商品选项迁移失败';
            die;
        }
        WebModel::where('id', $info['id'])->update(['remark' => '商品选项已迁移：' . date('Y-m-d H:i:s')]);

        // 商品信息
        try {
            $product = $this->createProducts($products, $dbstr, $category, $db_option_name_list, $db_option_name_value, $info);
        } catch (Exception $e) {
            WebModel::where('id', $info['id'])->update(['status' => 3, 'remark' => '商品迁移报错' . $e->getMessage(), 'end_time' => date('Y-m-d H:i:s')]);
            die('商品迁移报错');
        }
        if (!$product) {
            WebModel::where('id', $info['id'])->update(['status' => 3, 'remark' => '商品迁移失败', 'end_time' => date('Y-m-d H:i:s')]);
            echo '商品迁移失败';
            die;
        }
        WebModel::where('id', $info['id'])->update(['status' => 4, 'image_status' => 0, 'remark' => '迁移成功', 'end_time' => date('Y-m-d H:i:s')]);
        echo '迁移成功';
        die;
    }

    /**
     * @param $list
     * @param $dbstr
     * @param $category
     * @param $db_option_name_list
     * @param $db_option_name_value
     * @param $find
     * @return true
     * @throws Exception
     */
    public function createProducts($list, $dbstr, $category, $db_option_name_list, $db_option_name_value, $find): bool
    {
        // 清空商品数据
        Db::connect($dbstr)->table('oc_product')->where('product_id', '>', 0)->delete();
        Db::connect($dbstr)->table('oc_product_image')->where('product_id', '>', 0)->delete();
        Db::connect($dbstr)->table('oc_product_to_store')->where('product_id', '>', 0)->delete();
        Db::connect($dbstr)->table('oc_product_description')->where('product_id', '>', 0)->delete();
        Db::connect($dbstr)->table('oc_product_special')->where('product_id', '>', 0)->delete();
        Db::connect($dbstr)->table('oc_product_to_category')->where('product_id', '>', 0)->delete();
        Db::connect($dbstr)->table('oc_product_option')->where('product_id', '>', 0)->delete();
        Db::connect($dbstr)->table('oc_product_option_value')->where('product_id', '>', 0)->delete();

        $productData = [];

        foreach ($list as $key => $product) {
            $time = date('Y-m-d H:i:s');
            $images = array_filter(explode(',', $product['images']));
            $image = $images[0] ?? '';
            $image = $this->oss_url . parse_url($image)['path'];
            $productData[] = [
                'model' => $product['sku'],
                'sku' => $product['sku'],
                'upc' => '',
                'ean' => '',
                'jan' => '',
                'isbn' => '',
                'mpn' => '',
                'location' => '',
                'stock_status_id' => '1',
                'image' => $image,
                'manufacturer_id' => 0,
                'price' => $product['price'],
                'tax_class_id' => 0,
                'date_available' => date('Y-m-d'),
                'sort_order' => $key,
                'status' => $product['status'],
                'date_added' => $time,
                'date_modified' => $time,
                // 'group' => ''
            ];
        }

        // 添加到商品表
        if (!Db::connect($dbstr)->table('oc_product')->limit(1000)->insertAll($productData)) {
            return false;
        }

        $toCategory = $toAttributeOption = $description = $special = $toStore = $toImages = [];

        $product_list = Db::connect($dbstr)->table('oc_product')->column('product_id', 'sku');
        foreach ($list as $i => $goods) {
            $time = date('Y-m-d H:i:s');
            $product_id = $product_list[$goods['sku']] ?? 0;
            if ($product_id) {
                // 详情
                $description[] = [
                    'product_id' => $product_id,
                    'name' => $goods['name'],
                    'description' => $goods['description'],
                    'tag' => '',
                    'meta_title' => $goods['meta_title'],
                    'meta_keyword' => $goods['meta_keywords'],
                    'meta_description' => $goods['meta_description']
                ];

                $toStore[] = [
                    'product_id' => $product_id
                ];

                // 特价
                if ($goods['specials_price']) {
                    $special[] = [
                        'product_id' => $product_id,
                        'price' => $goods['specials_price'],
                        'date_start' => $time,
                        'date_end' => date('Y-m-d H:i:s', strtotime("+100 year")),
                    ];
                }

                // 附图
                $images = array_filter(explode(',', $goods['images']));
                foreach ($images as $img) {
                    $toImages[] = ['product_id' => $product_id, 'sort_order' => $i, 'image' => $this->oss_url . parse_url($img)['path']];
                }

                // 分类
                foreach ($goods['master_categorys'] as $collection) {
                    if (isset($category[(string)$collection])) {
                        $toCategory[] = ['product_id' => $product_id, 'category_id' => $category[(string)$collection]];
                    }
                }

                // 选项
                $attributeOption = $this->attributeOption($product_id, $goods['options'], $db_option_name_list);
                $toAttributeOption = array_merge($toAttributeOption, $attributeOption);
            }
        }

        // 商品选项
        if ($toAttributeOption) {
            Db::connect($dbstr)->table('oc_product_option')->limit(1000)->insertAll($toAttributeOption);
        }
        // 商品选项值
        $toAttribute = [];
        foreach ($list as $i => $goods) {
            $product_id = $product_list[$goods['sku']] ?? 0;
            if ($product_id) {
                $attribute = $this->attribute($dbstr, $product_id, $goods['options'], $goods['attribute'], $db_option_name_list, $db_option_name_value, $goods['specials_price']);
                $toAttribute = array_merge($toAttribute, $attribute);
            }
        }
        if ($toAttribute) {
            Db::connect($dbstr)->table('oc_product_option_value')->limit(1000)->insertAll($toAttribute);
        }
        // 商品详情
        if ($description) {
            Db::connect($dbstr)->table('oc_product_description')->limit(1000)->insertAll($description);
        }
        // 商品附图
        if ($toImages) {
            Db::connect($dbstr)->table('oc_product_image')->limit(1000)->insertAll($toImages);
        }
        // 商品分类
        if ($toCategory) {
            Db::connect($dbstr)->table('oc_product_to_category')->limit(1000)->insertAll($toCategory);
        }
        // 商品特价
        if ($special) {
            Db::connect($dbstr)->table('oc_product_special')->limit(1000)->insertAll($special);
        }
        if ($toStore) {
            Db::connect($dbstr)->table('oc_product_to_store')->limit(1000)->insertAll($toStore);
        }

        return true;
    }


    /**
     * opencart 分类导入
     * @param $list
     * @param $dbstr
     * @return array
     * @throws Exception
     */
    public function category($list, $dbstr): array
    {
        try {
            $categoryList = $this->categoryFormat($list);
            $category_parent_list = $this->getCategory($dbstr);
            $insertCategory = $insertStore = $insertPath = [];
            foreach ($categoryList as $key => $item) {
                $parent_id = 0;
                $parent_sku = $item['name'];
                if ($item['parent_sku']) {
                    $parent_sku = $item['parent_sku'] . '/' . $parent_sku;
                    $parent_id = $category_parent_list[$item['parent_sku']] ?? 0;
                }
                $description = [
                    'name' => $item['name'],
                    'description' => $item['title'],
                    'meta_title' => $item['name'],
                    'meta_keyword' => $item['name'],
                    'meta_description' => $item['name']
                ];
                $category_id = $category_parent_list[$item['title']] ?? 0;
                if ($category_id) {
                    Db::connect($dbstr)->table('oc_category')->where('category_id', $category_id)->update(['parent_id' => $parent_id, 'date_modified' => date('Y-m-d H:i:s')]);
                } else {
                    $category_id = Db::connect($dbstr)->table('oc_category_description')->insertGetId($description);
                    $insertCategory[] = [
                        'category_id' => $category_id,
                        'parent_id' => $parent_id,
                        'sort_order' => $key,
                        'column' => 0,
                        'date_added' => date('Y-m-d H:i:s'),
                        'date_modified' => date('Y-m-d H:i:s')
                    ];
                    $insertStore[] = [
                        'category_id' => $category_id,
                        'store_id' => 0
                    ];
                    $insertPath[] = [
                        'category_id' => $category_id,
                        'path_id' => $category_id,
                        'level' => 1,
                    ];
                }
                $category_parent_list[$parent_sku] = $category_id;
            }
            if ($insertCategory) {
                Db::connect($dbstr)->table('oc_category')->insertAll($insertCategory);
                Db::connect($dbstr)->table('oc_category_to_store')->insertAll($insertStore);
                Db::connect($dbstr)->table('oc_category_path')->insertAll($insertPath);
            }
            return $this->getCategory($dbstr);
        } catch (Exception $e) {
            return [];
        }
    }

    /**
     * @param $dbstr
     * @return array
     * @throws Exception
     */
    public function getCategory($dbstr): array
    {
        return Db::connect($dbstr)->table('oc_category_description cd')
            ->join('oc_category c', 'cd.category_id = c.category_id', 'LEFT')
            ->column('c.category_id', 'cd.description');
    }


    /**
     * @param $dbstr
     * @param $options
     * @return array
     * @throws Exception
     */
    public function option($dbstr, $options): array
    {
        $db_option_name_list = Db::connect($dbstr)->table('oc_option_description')->column('option_id', 'name');
        $db_option_name_value = [];
        foreach ($db_option_name_list as $db_option_name => $db_option_id) {
            $db_option_name_value[$db_option_name] = Db::connect($dbstr)->table('oc_option_value_description')->where('option_id', $db_option_id)->column('option_value_id', 'name');
        }

        $i = 1;
        $option_name_list = $option_value_list = [];
        foreach ($options as $option_name => $option_values) {
            $product_option_id = $db_option_name_list[(string)$option_name] ?? 0;
            if (!$product_option_id) {
                $product_option_id = Db::connect($dbstr)->table('oc_option_description')->insertGetId(['name' => (string)$option_name]);
                $option_name_list[] = [
                    'sort_order' => $i,
                    'option_id' => $product_option_id,
                    'type' => 'select'
                ];
                $db_option_name_list[(string)$option_name] = $product_option_id;
            }
            foreach ($option_values as $value_sort => $op_name_value) {
                $product_option_value_id = $db_option_name_value[(string)$option_name][(string)$op_name_value] ?? 0;
                if (!$product_option_value_id) {
                    $product_option_value_id = Db::connect($dbstr)->table('oc_option_value_description')->insertGetId(['name' => (string)$op_name_value, 'language_id' => 1, 'option_id' => $product_option_id]);
                    $option_value_list[] = [
                        'sort_order' => $value_sort,
                        'image' => '',
                        'option_id' => $product_option_id,
                        'option_value_id' => $product_option_value_id
                    ];
                    $db_option_name_value[(string)$option_name][(string)$op_name_value] = $product_option_value_id;
                }
            }
            $i++;
        }
        if ($option_name_list) {
            Db::connect($dbstr)->table('oc_option')->insertAll($option_name_list);
        }
        if ($option_value_list) {
            Db::connect($dbstr)->table('oc_option_value')->insertAll($option_value_list);
        }
        return [$db_option_name_list, $db_option_name_value];
    }

    public function attributeOption($product_id, $variants, $db_option_name_list)
    {
        $product_option = [];
        foreach ($variants as $var) {
            $option_id = $db_option_name_list[(string)$var['option_name']] ?? 0;
            if ($option_id) {
                $product_option[] = [
                    'product_id' => $product_id,
                    'option_id' => $option_id,
                    'value' => ''
                ];
            }
        }
        return $product_option;
    }

    /**
     * 商品属性值
     * @param $dbstr
     * @param $product_id
     * @param $variants
     * @param $attribute
     * @param $db_option_name_list
     * @param $db_option_name_value
     * @param $price
     * @return array
     * @throws Exception
     */
    public function attribute($dbstr, $product_id, $variants, $attribute, $db_option_name_list, $db_option_name_value, $price): array
    {
        $options = Db::connect($dbstr)->table('oc_product_option')->column('product_id,option_id,product_option_id');
        $optionList = [];
        foreach ($options as $option) {
            $optionList[$options['product_id'] . '_' . $option['option_id']] = $option['product_option_id'];
        }
        $option_price = [];
        if ($attribute) {
            $option_price = $this->getOptionPrice($attribute, $price);
        }
        $product_option_value = [];
        foreach ($variants as $var) {
            $option_id = $db_option_name_list[(string)$var['option_name']] ?? 0;
            if ($option_id) {
                $product_option_id = $optionList[$product_id . '_' . $option_id] ?? 0;
            }
            $var_option_value = array_unique($var['option_value']);
            foreach ($var_option_value as $option_value) {
                $option_value_id = $db_option_name_value[(string)$var['option_name']][(string)$option_value] ?? 0;
                if ($option_id && $option_value_id && !empty($product_option_id)) {
                    $add_price = $option_price[$option_value] ?? 0;
                    $price_prefix = '+';
                    if ($add_price < 0) {
                        $price_prefix = '-';
                    }
                    $product_option_value[] = [
                        'product_option_id' => $product_option_id,
                        'product_id' => $product_id,
                        'option_id' => $option_id,
                        'option_value_id' => $option_value_id,
                        'price' => abs($add_price),
                        'price_prefix' => $price_prefix
                    ];
                }
            }
        }
        return $product_option_value;
    }


    public function preload_image($info, $dbStr)
    {

        $name = ['bestsellers', 'new arrivals', 'featured', 'BESTSELLERS', 'NEW ARRIVALS', 'FEATURED'];
        $where = [
            'website_id' => $info['id'],
            'rank' => '0',
        ];
        try {
            // 获取 oc_layout_module
            $codes = Db::connect($dbStr)->table('oc_layout_module')->where('layout_id', 1)->column('code');
            $size = [];
            foreach ($codes as $code) {
                $code = explode('.', $code);
                $setting = Db::connect($dbStr)->table('oc_module')->where('name', 'in', $name)->where('code', $code[0])->value('setting');
                $setting = json_decode($setting, true);
                $size[] = [
                    'width' => $setting['width'] ?? 400, 'height' => $setting['height'] ?? 400
                ];
            }
            $width = Db::connect($dbStr)->table('oc_setting')->where('key', 'config_image_product_width')->value('value');
            $height = Db::connect($dbStr)->table('oc_setting')->where('key', 'config_image_product_height')->value('value');
            $size[] = [
                'width' => $width ?? 400, 'height' => $height ?? 400
            ];

            // 获取网站主图
            $image_list = ImgModel::where($where)->where('image_status', 0)->field("id,yy_image,oss_image")->order('id')->limit(1000)->select()->toArray();
            if (!$image_list) {
                WebModel::where('id', $info['id'])->update(['image_status' => 4, 'image_end' => date('Y-m-d H:i:s')]);
                // 清除数据缓存
                $option = array('ssl' => array('verify_peer' => false, 'verify_peer_name' => false));
                file_get_contents("https://{$info['domain']}/{$this->web_url}?token=y1goj8Pbr3VzPdS&active=clearSql", false, stream_context_create($option));
            }

            // 图片迁移中
            $image_ids = array_column($image_list, 'id');
            ImgModel::where('id', 'in', $image_ids)->update(['image_status' => 2, 'image_start' => date('Y-m-d H:i:s')]);

            $this->longRange($image_list, $info, $size);
        } catch (Exception $e) {
            WebModel::where('id', $info['id'])->update(['image_status' => 4, 'image_end' => date('Y-m-d H:i:s')]);
        }
        return true;
    }

    /**
     * @param $image_list
     * @param $info
     * @param $size
     * @param bool $bool
     * @return true
     */
    public function longRange($image_list, $info, $size, $bool = false): bool
    {
        $url = "https://{$info['domain']}/{$this->web_url}";
        $img_arr = array_chunk($image_list, 100);
        foreach ($img_arr as $arr) {
            $list = ['size' => $size, 'list' => $arr];
            $data = postUrl($url, ['token' => 'y1goj8Pbr3VzPdS', 'data' => json_encode($list)]);
            if (!$bool) {
                $arrIds = array_column($arr, 'id');
                if (isset($data['code'])) {
                    ImgModel::where('id', 'in', $arrIds)->update(['image_status' => 1, 'remark' => '缩略图成功', 'image_end' => date('Y-m-d H:i:s')]);
                } else {
                    ImgModel::where('id', 'in', $arrIds)->update(['image_status' => 3, 'image_end' => date('Y-m-d H:i:s')]);
                }
            }
        }
        return true;
    }

}